'use client'

import { createClient } from "@connectrpc/connect";
import { createConnectTransport } from "@connectrpc/connect-web";
import { useRef, useState } from "react";
import { CalculatorService } from "../../gen/pts/f/v1/calculator_pb";

type gRPCRequest = {
  "prior": number | null,
  "post": number | null,
  "op": number | null, // 0: +, 1: -, 2: *, 3: / 
}

type gRPCResponse = {
  "result": number | null,
}

export default function Calculator() {
  const transport = createConnectTransport({
    baseUrl: "http://localhost:8080"
  });
  const opReq = useRef<gRPCRequest>({
    "prior": null,
    "post": null,
    "op": null,
  })
  let [board, setBoard] = useState(0);
  let [op, setOp] = useState<number | null>(null);
  let [isNegative, setNegative] = useState(0);
  let [isErr, setErr] = useState(false);

  let push = (n: number) => {
    if (isErr) {
      setErr(false);
    }
    if (op !== null && n !== -1 && n !== -2) {
      if (opReq.current.post !== null) {
        calc();
        opReq.current.post = null;
      }
      opReq.current.prior = board * (isNegative === 1 ? -1 : 1);
      setNegative(0);
      setBoard(n);
      setOp(null);
      return;
    }
    if (board >= 99999999 && n !== -1 && n !== -2) {
      return;
    }
    switch (n) {
      case 0:
        if (board === 0) {
          setBoard(n);
          return;
        }
        setBoard(board * 10 + n);
        break;
      case -1:
        opReq.current = {
          "prior": null,
          "post": null,
          "op": null,
        }
        setBoard(0);
        setOp(null);
        return;
      case -2:
        setBoard(Math.floor(board / 10));
        if (board === 0 && isNegative === 1) {
          setNegative(0);
        }
        return;
      default:
        setBoard(board * 10 + n);
    }
  }
  let pressOp = (pop: number) => {
    if (pop === op) {
      console.debug("press same op")
      setOp(null);
      return;
    }
    setOp(pop);
    opReq.current.op = pop;
  }
  let calc = async () => {
    console.debug("origin opReq is", opReq.current);
    if (opReq.current.post === null) {
      console.debug("now board", board);
      opReq.current.post = board * (isNegative === 1 ? -1 : 1);
      console.debug("now set opReqs post");
      setNegative(0);
    }
    console.debug("opReg is", opReq.current);
    const res = await toBak(opReq.current);
    console.debug("remote response is", res);
    if (res.result === null) {
      setBoard(0);
      return;
    }
    setBoard(Math.abs(res.result));
    if (res.result < 0) {
      setNegative(1);
    }
    setOp(null);
    opReq.current.prior = res.result;
  }
  let toBak = async (req: gRPCRequest) => {
    const client = createClient(CalculatorService, transport);
    const res = await client.calculate({
      prior: req.prior!,
      post: req.post!,
      op: req.op!,
    });
    console.debug("remote response is", res);
    return { result: res.result };
  }

  return (
    <div className="flex min-h-screen flex-col items-center justify-center bg-gray-100">
      <div className="bg-white rounded-lg shadow-xl p-6">
        <div className="grid grid-cols-4 gap-3 w-80">
          {/* Display */}
          <div className="col-span-4 bg-black text-white text-right text-3xl p-4 rounded mb-4 min-h-16 flex items-center justify-end relative">
            {isNegative ? '-' : ''}{board}
            {isErr && <div className="absolute top-1 left-1 text-xs text-red-400">ERR</div>}
          </div>

          {/* Row 1 */}
          <button 
            className="bg-gray-200 hover:bg-gray-300 text-black font-medium py-4 px-4 rounded"
            onClick={() => setNegative(isNegative === 0 ? 1 : 0)}
          >
            ±
          </button>
          <button 
            className="bg-gray-200 hover:bg-gray-300 text-black font-medium py-4 px-4 rounded"
            onClick={() => push(-1)}
          >
            C
          </button>
          <button 
            className="bg-gray-200 hover:bg-gray-300 text-black font-medium py-4 px-4 rounded"
            onClick={() => push(-2)}
          >
            ⌫
          </button>
          <button 
            className={`${op === 3 ? 'bg-orange-500' : 'bg-orange-400'} hover:bg-orange-500 text-white font-medium py-4 px-4 rounded`}
            onClick={() => pressOp(3)}
          >
            ÷
          </button>

          {/* Row 2 */}
          <button 
            className="bg-gray-300 hover:bg-gray-400 text-black font-medium py-4 px-4 rounded"
            onClick={() => push(7)}
          >
            7
          </button>
          <button 
            className="bg-gray-300 hover:bg-gray-400 text-black font-medium py-4 px-4 rounded"
            onClick={() => push(8)}
          >
            8
          </button>
          <button 
            className="bg-gray-300 hover:bg-gray-400 text-black font-medium py-4 px-4 rounded"
            onClick={() => push(9)}
          >
            9
          </button>
          <button 
            className={`${op === 2 ? 'bg-orange-500' : 'bg-orange-400'} hover:bg-orange-500 text-white font-medium py-4 px-4 rounded`}
            onClick={() => pressOp(2)}
          >
            ×
          </button>

          {/* Row 3 */}
          <button 
            className="bg-gray-300 hover:bg-gray-400 text-black font-medium py-4 px-4 rounded"
            onClick={() => push(4)}
          >
            4
          </button>
          <button 
            className="bg-gray-300 hover:bg-gray-400 text-black font-medium py-4 px-4 rounded"
            onClick={() => push(5)}
          >
            5
          </button>
          <button 
            className="bg-gray-300 hover:bg-gray-400 text-black font-medium py-4 px-4 rounded"
            onClick={() => push(6)}
          >
            6
          </button>
          <button 
            className={`${op === 1 ? 'bg-orange-500' : 'bg-orange-400'} hover:bg-orange-500 text-white font-medium py-4 px-4 rounded`}
            onClick={() => pressOp(1)}
          >
            −
          </button>

          {/* Row 4 */}
          <button 
            className="bg-gray-300 hover:bg-gray-400 text-black font-medium py-4 px-4 rounded"
            onClick={() => push(1)}
          >
            1
          </button>
          <button 
            className="bg-gray-300 hover:bg-gray-400 text-black font-medium py-4 px-4 rounded"
            onClick={() => push(2)}
          >
            2
          </button>
          <button 
            className="bg-gray-300 hover:bg-gray-400 text-black font-medium py-4 px-4 rounded"
            onClick={() => push(3)}
          >
            3
          </button>
          <button 
            className={`${op === 0 ? 'bg-orange-500' : 'bg-orange-400'} hover:bg-orange-500 text-white font-medium py-4 px-4 rounded`}
            onClick={() => pressOp(0)}
          >
            +
          </button>

          {/* Row 5 */}
          <button 
            className="col-span-2 bg-gray-300 hover:bg-gray-400 text-black font-medium py-4 px-4 rounded"
            onClick={() => push(0)}
          >
            0
          </button>
          <button 
            className="bg-gray-300 hover:bg-gray-400 text-black font-medium py-4 px-4 rounded"
          >
            .
          </button>
          <button 
            className="bg-orange-400 hover:bg-orange-500 text-white font-medium py-4 px-4 rounded"
            onClick={() => calc()}
          >
            =
          </button>
        </div>
      </div>
    </div>
  );
}